#ifndef AVALON_BUFFEREDREADER_HPP
#define AVALON_BUFFEREDREADER_HPP
#include "Avalon/Base/Handle.hpp"
#include "Avalon/IO/PipedMessageReader.hpp"
#include "Avalon/IO/PipedMessageWriter.hpp"
#include "Avalon/IO/Reader.hpp"

namespace Avalon {
namespace IO {

  /*! \class BufferedReader
   *  \brief Buffers all data read from another Reader.
   *  \author Kamal Mansouri <kranar@hotmail.com>
   */
  class BufferedReader : public Reader {
    public:

      //! Constructs a BufferedReader.
      /*!
        \param source The Reader to buffer.
      */
      BufferedReader(Carry<Reader> source);

      virtual ~BufferedReader();

      virtual bool IsAtEndOfDataSource();

      virtual Threading::Async<int>::Ptr Read(Buffer* destination);

      virtual Threading::Async<int>::Ptr Read(void* destination, int size);

      virtual Threading::Async<int>::Ptr Read(Buffer* destination, int size);

    private:
      boost::mutex m_mutex;
      Carry<Reader> m_source;
      PipedMessageReader m_reader;
      PipedMessageWriter m_writer;
      bool m_isBuffering;
      Buffer m_destination;

      void EnableBuffering();
      void OnRead(const Avalon::Threading::Async<int>::Ptr& result);
  };
}
}

#endif // AVALON_BUFFEREDREADER_HPP
